package isp.apps.example.shoppingcart.action;

import isp.apps.example.shoppingcart.domain.CartItem;
import isp.apps.example.shoppingcart.domain.CompletedOrder;
import isp.apps.example.shoppingcart.domain.OrderStatus;
import isp.apps.example.shoppingcart.domain.ShippingCalculator;
import isp.apps.example.shoppingcart.domain.ShippingCalculatorFactory;
import isp.apps.example.shoppingcart.domain.ShippingOption;

import isp.apps.example.shoppingcart.domain.ShoppingCartValidator;
import isp.apps.example.shoppingcart.persistence.OrderStatusDirectory;
import isp.apps.example.shoppingcart.persistence.ShippingOptionsDirectory;
import isp.apps.example.shoppingcart.persistence.CartItemsRepository;
import isp.apps.example.shoppingcart.persistence.CompletedOrderRepository;
import isp.apps.example.shoppingcart.persistence.factory.CompletedOrderPersistenceFactory;
import isp.apps.example.shoppingcart.persistence.factory.OrderStatusPersistenceFactory;
import isp.apps.example.shoppingcart.persistence.factory.ShippingOptionsPersistenceFactory;
import isp.apps.example.shoppingcart.persistence.factory.CartItemsPersistenceFactory;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.List;

public class ConfirmationAction extends ShoppingAction
{

  private String fName, lName, address1, address2, city, state, zip, phone, ccType, ccNumber, ccSecurity, ccExpiration, chosenShippingOption;

  private ShippingOptionsDirectory sod = ShippingOptionsPersistenceFactory.getShippingOptionsDirectory();
  private Integer orderStatusId = null;

  public ConfirmationAction()
  {
  }

  /** Execute is called by webwork auto-magically when any request is sent for Confirmation.action
   * @return Success or Input (essentially a "re-do" of parent action as defined in xwork.xml)
   */
  public String execute()
  {
    if (getCart().getCartItems().size() < 1)
    {
       addActionError("You must have at least one item in your cart to proceed to checkout");
       return "CartIsEmpty";
    }
    loadMinOrderStatus();

    validate();
    if (hasActionErrors())
      return INPUT;

    if (getCart().getOrderId() == null)
      writeOrderToDb();

    return SUCCESS;
  }

  /**
   * Gets an OrderStatusDirectory from the OrderStatusPersistenceFactory and reads the lowest possible step
   * to use as the default OrderStep for a new order.
   */
  public void loadMinOrderStatus()
  {
    OrderStatusDirectory osd = OrderStatusPersistenceFactory.getOrderStatusDirectory();
    List minStatusList = osd.getMinValidStatus();
    if (minStatusList.size() > 0)
    {
      OrderStatus minStatus = (OrderStatus) minStatusList.get(0);
      orderStatusId = minStatus.getId();
    }
  }

  /**
   * Gets a CartItemRepository from the PersistenceFactory to write the OrderItems to storage.
   * Hydrates a CompletedOrder object for writing to storage.
   */
  public void writeOrderToDb()
  {
    CartItemsRepository cir = CartItemsPersistenceFactory.getCartItemsRepository();
    Collection cartItems = getCart().getCartItems();
    CompletedOrderRepository cor =
      CompletedOrderPersistenceFactory.getCompletedOrderRepository();
    CompletedOrder co = new CompletedOrder();
    hydrateOrder(co);
    for (Iterator i = cartItems.iterator(); i.hasNext(); )
    {
      CartItem ci = (CartItem) i.next();
      ci.setOrder(co);
      co.getOrderItems().add(ci);
    }
    cor.saveCompletedOrder(co);
    getCart().setOrderId(co.getId());
  }

  /** sets all the fields of the CompletedOrder object using form input
   * 
   */
  public void hydrateOrder(CompletedOrder co)
  {
    ShippingOption so = sod.getOptionById(new Integer(chosenShippingOption));
    co.setFirstName(fName);
    co.setZip(zip);
    co.setState(state);
    co.setPhone(phone);
    co.setLastName(lName);
    co.setCity(city);
    co.setCcNumber(ccNumber);
    co.setCcType(ccType);
    co.setCcSecurity(ccSecurity);
    co.setCcExpiration(ccExpiration);
    co.setAddress1(address1);
    co.setAddress2(address2);
    Calendar today = new GregorianCalendar();
    today.setTime(new Date());
    co.setCalendar(today);
    ShippingCalculator shippingCalc = ShippingCalculatorFactory.getShippingCalculator();
    Collection c = getCart().getCartItems();
    List l = new ArrayList(c.size());
    for (Iterator i = c.iterator(); i.hasNext();)
       l.add(i.next());
    shippingCalc.getShippingCost(l,so);
    co.setShippingCost(so.getRate());
  }

  public void setFName(String fName)
  {
    this.fName = fName.trim();
  }

  public void setLName(String lName)
  {
    this.lName = lName.trim();
  }

  public void setAddress1(String address1)
  {
    this.address1 = address1.trim();
  }

  public void setAddress2(String address2)
  {
    this.address2 = address2.trim();
  }

  public void setState(String state)
  {
    this.state = state.trim();
  }

  public void setZip(String zip)
  {
    this.zip = zip;
  }

  public void setPhone(String phone)
  {
    this.phone = phone;
  }

  public void setCcType(String ccType)
  {
    this.ccType = ccType.trim();
  }

  public void setCcNumber(String ccNumber)
  {
    this.ccNumber = ccNumber;
  }

  public void setCcSecurity(String ccSecurity)
  {
    this.ccSecurity = ccSecurity;
  }

  public void setCcExpiration(String ccExpiration)
  {
    this.ccExpiration = ccExpiration;
  }

  public String getFName()
  {
    return fName;
  }

  public String getLName()
  {
    return lName;
  }

  public String getAddress1()
  {
    return address1;
  }

  public String getAddress2()
  {
    return address2;
  }

  public String getState()
  {
    return state;
  }

  public String getZip()
  {
    return zip;
  }

  public String getPhone()
  {
    return phone;
  }

  public String getCcType()
  {
    return ccType;
  }

  public String getCcNumber()
  {
    return ccNumber;
  }

  public String getCcSecurity()
  {
    return ccSecurity;
  }

  public String getCcExpiration()
  {
    return ccExpiration;
  }

  public void setCity(String city)
  {
    this.city = city;
  }

  public String getCity()
  {
    return city;
  }

  public void validate()
  {
    String temp;
    ShoppingCartValidator scv = new ShoppingCartValidator();
    if (orderStatusId == null)
    {
      addActionError("There has been an error processing your order, please contact " +
                     "us by phone to complete your order.  We apologize for the inconvenience");
      return;
    }

    temp = fName;
    if ((fName = scv.checkText(fName)) == null)
    {
      addActionError("Please specify a valid name: \"" + temp + "\"");
      return;
    }

    //check lName
    temp = lName;
    if ((lName = scv.checkText(lName)) == null)
    {
      addActionError("Empty Last Name field: \"" + temp + "\"");
      return;
    }

    //check address1
    if ((address1 = scv.checkText(address1)) == null)
    {
      addActionError("Empty First Address field");
      return;
    }

    //check address2 CAN BE BLANK

    //city
    if ((city = scv.checkText(city)) == null)
    {
      addActionError("Empty City field.");
      return;
    }

    //check state
    if ((state = scv.checkText(state)) == null)
    {
      addActionError("Empty State field.");
      return;
    }

    //check zip
    temp = zip;
    if ((zip = scv.checkZipCode(zip)) ==null)
      {
        addActionError("Zip code must be exactly 5 numbers: \"" + temp + "\"");
        return;
      }


    //check phone
    temp = phone;
    if ((phone = scv.checkPhone(phone)) == null)
    {
      addActionError("Phone Number must be exactly 10 numbers digits (includes area code): \"" + temp + "\"");
      return;
    }


    //check ccType
    if ((ccType = scv.checkText(ccType)) == null)
    {
      addActionError("Empty Credit Card Type field (Visa / MasterCard / etc): \"" +ccType+ "\"");
      return;
    }


    //check ccNumber
    temp = ccNumber;
    if ((ccNumber = scv.checkCCNumber(ccNumber)) == null)
    {
      addActionError("Credit Card Number must be exactly 16 digits: \"" + temp + "\"");
      return;
    }


    //check ccSecurity
    temp = ccSecurity;
    if ((ccSecurity = scv.checkCCSecurity(ccSecurity)) == null)
    {
      addActionError("Credit Card Security number should be 3 digits: \"" +temp + "\"");
      return;
    }

    //check ccExpiration;
    temp = ccExpiration;
    if ((ccExpiration = scv.checkCCExpiration(ccExpiration)) == null)
    {
      addActionError("Credit Card expiration date should be 4 digits: \"" +temp + "\"");
      return;
    }

    if ((chosenShippingOption = scv.checkNumber(chosenShippingOption)) == null)
    {
      addActionError("Please choose a valid shipping option");
      return;
    }
    //end validate
  }


  public void setChosenShippingOption(String shippingOption)
  {
    this.chosenShippingOption = shippingOption;
  }

  public String getChosenShippingOption()
  {
    return chosenShippingOption;
  }


}
